package cn.wolfcode.luowowo.redis.service.impl;

import cn.wolfcode.luowowo.domain.UserInfo;
import cn.wolfcode.luowowo.exception.LogicException;
import cn.wolfcode.luowowo.redis.service.IUserInfoRedisService;
import cn.wolfcode.luowowo.util.Consts;
import cn.wolfcode.luowowo.redis.util.RedisKeys;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.concurrent.TimeUnit;

/**
 * 用户操作Redis数据库的业务类
 */
@Service
public class UserInfoRedisServiceImpl implements IUserInfoRedisService {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public void setVerifyCode(String phone, String code) {
        //key
        //String key = "verify_code:" + phone;
        //使用枚举类来拼Redis的key
        String key = RedisKeys.VERIFY_CODE.join(phone);
        //保存进Redis：参数1：key；参数2：value；参数3：时长；参数4：时间单位
        redisTemplate.opsForValue().set(key, code, RedisKeys.VERIFY_CODE.getTime(), TimeUnit.SECONDS);
    }

    @Override
    public String getVerifycode(String key) {
        //查询验证码
        return redisTemplate.opsForValue().get(key);
    }

    @Override
    public void setToken(String token, UserInfo userInfo) {
        //保存登录的用户信息

        //key可读性：加前缀
        String key = RedisKeys.USER_LOGIN_TOKEN.join(token);
        //key加了前缀，value要toJsonString，时间常量通过枚举拿到，单位是 s
        redisTemplate.opsForValue().set(key, JSON.toJSONString(userInfo), RedisKeys.USER_LOGIN_TOKEN.getTime(), TimeUnit.SECONDS);
    }

    @Override
    public void setCount(String count, String phone, long time) {
        //存限制次数 send_count:3
        String key = RedisKeys.SEND_COUNT.join(phone);
        redisTemplate.opsForValue().set(key, Consts.SEND_COUNT.toString());
        //在次数范围内，延长有效时间，当次数不满足的时候value<=0，时间是5分钟，5分钟之后失效，可以继续发验证码
        redisTemplate.expire(key, time, TimeUnit.SECONDS);
    }

    @Override
    public void ckeckSendCount(String phone) {
        String key = RedisKeys.SEND_COUNT.join(phone);
        redisTemplate.opsForValue().set(key, "0");

        redisTemplate.opsForValue().increment(key, 1L);
        String count = redisTemplate.opsForValue().get(key);
        Integer times = new Integer(count);
        if (times == 1) {
            //设置失效时间
            redisTemplate.expire(key, Consts.VERIFY_CODE_VAI_TIME, TimeUnit.SECONDS);
        }
        if (times > 3) {
            throw new LogicException("您的验证次数已达上限，请5分钟之后重试！");
        }
    }

    @Override
    public Long getCount(String phone) {
        //查到value 即次数
        String key = RedisKeys.SEND_COUNT.join(phone);
        String count = redisTemplate.opsForValue().get(key);
        return count==null ? 0 : new Long(count);
    }

    @Override
    public void decrementCount(String phone) {
        //2.成功发送一次短信，次数减1
        String key = RedisKeys.SEND_COUNT.join(phone);
        //次数-1，成功一次，改变value，value<=0时，机会用完，等下一个五分钟
        redisTemplate.opsForValue().decrement(key, 1);
    }

    //获得过期时间
    @Override
    public Long getExpireSeconds(String phone) {
        String key = RedisKeys.SEND_COUNT.join(phone);
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    //判断key是否存在
    @Override
    public boolean hasKey(String phone) {
        String key = RedisKeys.SEND_COUNT.join(phone);
        Boolean result = redisTemplate.hasKey(key);
        if (result != null)
            return result;
        return false;
    }

    /**
     * 删除一个或多个key
     *
     * @param phones
     */
    public void del(String... phones) {
        String key = RedisKeys.SEND_COUNT.join(phones);
        if (phones.length < 1) {
            new Exception("请输入参数").printStackTrace();
        } else if (phones.length > 1) {
            redisTemplate.delete(CollectionUtils.arrayToList(phones));
        } else {
            redisTemplate.delete(phones[0]);
        }
    }

    @Override
    public void setCount(String newCount, String phone) {
        String key = RedisKeys.SEND_COUNT.join(phone);
        redisTemplate.opsForValue().set(key, newCount);
    }

    //通过token查询用户信息
    @Override
    public UserInfo getUserInfoByToken(String token) {
        //拼出key
        String key = RedisKeys.USER_LOGIN_TOKEN.join(token);
        //判断是否有key
        if (redisTemplate.hasKey(key)) {
            //注意：存在该对象，需要将数据的时效延长
            redisTemplate.expire(key, Consts.USER_INFO_TOKEN_VAI_TIME * 60L, TimeUnit.SECONDS);
            String userStr = redisTemplate.opsForValue().get(key);
            //返回的是字符串，controller需要的是json格式的对象
            return JSON.parseObject(userStr, UserInfo.class);//指定将那个字符串解析成什么类型的对象
        }
        //key不存在返回null
        return null;
    }

    @Override
    public void deleteCount(String phone) {
        String key = RedisKeys.SEND_COUNT.join(phone);
        redisTemplate.opsForValue().set(key, "0",  60L, TimeUnit.SECONDS);
    }


}
